package com.iamback.dy.examine.config.async;

import java.lang.reflect.Method;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

@Configuration
public class AsyncConfig implements AsyncConfigurer {
	private static final Logger log = LoggerFactory.getLogger(AsyncConfig.class);
	/**
	 * Set the ThreadPoolExecutor's core pool size.
	 */
	private static final int CORE_POOL_SIZE = 10;

	/**
	 * Set the ThreadPoolExecutor's maximum pool size.
	 */
	private static final int MAX_POOL_SIZE = 90;

	/**
	 * Set the capacity for the ThreadPoolExecutor's BlockingQueue.
	 */
	private static final int QUEUE_CAPACITY = 20;

	/**
	 * 通过重写getAsyncExecutor方法，制定默认的任务执行由该方法产生
	 * 
	 * 配置类实现AsyncConfigurer接口并重写getAsyncExcutor方法，并返回一个ThreadPoolTaskExevutor
	 * 这样我们就获得了一个基于线程池的TaskExecutor
	 */
	@Override
	public Executor getAsyncExecutor() {
		ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
		taskExecutor.setCorePoolSize(CORE_POOL_SIZE-2);// 线程池维护线程的最少数量
		taskExecutor.setMaxPoolSize(MAX_POOL_SIZE-10);// 线程池维护线程的最大数量
		taskExecutor.setAwaitTerminationSeconds(60 * 15);// 等待时间 （默认为0，此时立即停止），并没等待xx秒后强制停止
		taskExecutor.setQueueCapacity(QUEUE_CAPACITY);// 线程池所使用的缓冲队列
		taskExecutor.setWaitForTasksToCompleteOnShutdown(true);//等待任务在关机时完成--表明等待所有线程执行完
		taskExecutor.setThreadNamePrefix("Async-");//  线程名称前缀
		taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
		taskExecutor.initialize();
		return taskExecutor;
	}
	
	@Bean("exAsync")
	public Executor getExAsync() {
		ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
		executor.setCorePoolSize(CORE_POOL_SIZE - 8);
		executor.setMaxPoolSize(MAX_POOL_SIZE -60);
		executor.setQueueCapacity(QUEUE_CAPACITY - 15);
		executor.setAwaitTerminationSeconds(60 * 15);// 等待时间 （默认为0，此时立即停止），并没等待xx秒后强制停止
		executor.setWaitForTasksToCompleteOnShutdown(true);//等待任务在关机时完成--表明等待所有线程执行完
		executor.setThreadNamePrefix("exAsync-");
		// rejection-policy：当pool已经达到max size的时候，如何处理新任务
		// CALLER_RUNS：不在新线程中执行任务，而是有调用者所在的线程来执行 
		executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
		executor.initialize();
		return executor;
	}	
	@Bean("distributionAsync")
	public Executor getDistributionAsync() {
		ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
		executor.setCorePoolSize(CORE_POOL_SIZE - 8);
		executor.setMaxPoolSize(MAX_POOL_SIZE -60);
		executor.setQueueCapacity(QUEUE_CAPACITY - 15);
		executor.setAwaitTerminationSeconds(60 * 15);// 等待时间 （默认为0，此时立即停止），并没等待xx秒后强制停止
		executor.setWaitForTasksToCompleteOnShutdown(true);//等待任务在关机时完成--表明等待所有线程执行完
		executor.setThreadNamePrefix("exAsync-distribution-EX");
		// rejection-policy：当pool已经达到max size的时候，如何处理新任务
		// CALLER_RUNS：不在新线程中执行任务，而是有调用者所在的线程来执行 
		executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
		executor.initialize();
		return executor;
	}	
	@Bean("sysAsync")
	public Executor getSysAsync() {
		ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
		executor.setCorePoolSize(CORE_POOL_SIZE - 8);
		executor.setMaxPoolSize(MAX_POOL_SIZE -60);
		executor.setQueueCapacity(QUEUE_CAPACITY - 15);
		executor.setAwaitTerminationSeconds(60 * 15);// 等待时间 （默认为0，此时立即停止），并没等待xx秒后强制停止
		executor.setWaitForTasksToCompleteOnShutdown(true);//等待任务在关机时完成--表明等待所有线程执行完
		executor.setThreadNamePrefix("sysAsync-");
		// rejection-policy：当pool已经达到max size的时候，如何处理新任务
		// CALLER_RUNS：不在新线程中执行任务，而是有调用者所在的线程来执行 
		executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
		executor.initialize();
		return executor;
	}	
	
	@Override
	public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
		return new MyAsyncExceptionHandler();
	}

	/**
	 * 自定义异常处理类
	 * 
	 * @author hry
	 *
	 */
	class MyAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {

		@Override
		public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {
			log.info("-------------》》》捕获线程异常信息");
			log.info("Exception message - " + throwable.getMessage());
			log.info("Method name - " + method.getName());
			for (Object param : obj) {
				log.info("Parameter value - " + param);
			}
		}

	}
}